import React, {ReactNode, useEffect, useMemo, useState} from "react"
import FormDrawer from "./FormDrawer";
import {Button, Form, Input, InputNumber, Row, Space, Typography} from "antd";
import {DeleteOutlined, EditOutlined, PlusOutlined} from "@ant-design/icons";
import TextArea from "antd/es/input/TextArea";
import {useForm} from "antd/es/form/Form";
import {NumberIdAndName} from "../types/BasicModels";
import {arrayMove, SortableContext, useSortable, verticalListSortingStrategy} from "@dnd-kit/sortable";
import {DndContext, MouseSensor, PointerSensor, useSensor, useSensors} from "@dnd-kit/core";
import {CSS} from '@dnd-kit/utilities';
import {restrictToVerticalAxis} from "@dnd-kit/modifiers";
import ArrayUtils from "@zxy-cn/array-utils";
import {GoodsItem, GoodsSelectorItem} from "./GoodsWithSubGoodsSelector";
import {
    configureMarketSettlementPlan,
    ConfigureMarketSettlementPlanResponse,
    ConfigureMarketSettlementPlanRuleRequest,
    ConfigureMarketSettlementPlanRuleResponse,
    reconfigureMarketSettlementPlan
} from "../apis/MarketSettlementPlanApi";
import {
    GoodsMatcherConditionDescription,
    GoodsMatcherRuleFormItems, useGoodsMatcherConditions,
    useQueryGoodsMatcherBasicData
} from "./GoodsMatcherRuleFormItems";


export interface EditMarketShoppingGuideSalaryPlanDrawerProps {
    open: boolean
    onClose: () => void
    initialValue?: ConfigureMarketSettlementPlanResponse
    onCompleted: (value: ConfigureMarketSettlementPlanResponse) => void
    marketId: number
}


const EditMarketShoppingGuideSalaryPlanDrawer: React.FC<EditMarketShoppingGuideSalaryPlanDrawerProps> = (props) => {
    let [form] = useForm();

    return (
        <FormDrawer<ConfigureMarketSettlementPlanResponse> title={"配置工资方案"} open={props.open}
                                                           onClose={props.onClose}
                                                           initialValues={props.initialValue}
                                                           onConfirm={async (request) => {
                                                               const func = props.initialValue ? reconfigureMarketSettlementPlan : configureMarketSettlementPlan
                                                               let response = await func(props.marketId, {
                                                                   rules: request.rules.map(item => {
                                                                       return {
                                                                           ...item,
                                                                           includedCategoryIds: item.includedCategories.map(it => it.id),
                                                                           includedBrandIds: item.includedBrands.map(it => it.id),
                                                                           includedBrandTagIds: item.includedBrandTags.map(it => it.id),
                                                                           includedGoodsIds: item.includedGoodsList.map(it => it.id),
                                                                       }
                                                                   })
                                                               });
                                                               props.onCompleted(response.data)
                                                           }} form={form}>
            <Form.Item name={"rules"} label={"规则"}>
                <MarketSettlementRuleListEditor/>
            </Form.Item>
        </FormDrawer>
    )
}

export default EditMarketShoppingGuideSalaryPlanDrawer


export interface MarketSettlementRuleListEditorProps {
    value?: Array<ConfigureMarketSettlementPlanRuleResponse>
    onChange?: (value: Array<ConfigureMarketSettlementPlanRuleResponse>) => void
}

const MarketSettlementRuleListEditor: React.FC<MarketSettlementRuleListEditorProps> = (props) => {
    const {goodsBrands, goodsCategories, goodsBrandTags} = useQueryGoodsMatcherBasicData();

    const [editingValue, setEditingValue] = useState<ConfigureMarketSettlementPlanRuleRequest>()

    return <Space direction={"vertical"} style={{width: "100%"}}>
        <MarketSettlementPlanList goodsCategories={goodsCategories}
                                  goodsBrandTags={goodsBrandTags}
                                  goodsBrands={goodsBrands}
                                  value={props.value}
                                  onChange={props.onChange}/>
        <Space>
            <Button type="dashed" onClick={() => {
                // open drawer
                setEditingValue({
                    fixed: 0,
                    includedBrandIds: [],
                    includedCategoryIds: [],
                    includedBrandTagIds: [],
                    includedGoodsIds: [],
                    name: "",
                })
            }} block icon={<PlusOutlined/>}>
                添加固定费用
            </Button>
            <Button type="dashed" onClick={() => {
                // open drawer
                setEditingValue({
                    commissionPercentage: 0,
                    includedBrandIds: [],
                    includedCategoryIds: [],
                    includedBrandTagIds: [],
                    includedGoodsIds: [],
                    name: "",
                })
            }} block icon={<PlusOutlined/>}>
                添加提成
            </Button>
        </Space>

        <MarketSettlementPlanRuleFormDrawer open={!!editingValue} initialValue={editingValue}
                                            onClose={() => setEditingValue(undefined)}
                                            onCompleted={(value, extra) => {
                                                let array = Array.from(props.value ?? [])
                                                array.push({
                                                    ...value,
                                                    includedBrands: value.includedBrandIds.map(it => goodsBrands.find(i => i.id === it)).filter(Boolean).map(it => it!!),
                                                    includedCategories: value.includedCategoryIds.map(it => goodsCategories.find(i => i.id === it)).filter(Boolean).map(it => it!!),
                                                    includedBrandTags: value.includedBrandTagIds.map(it => goodsBrandTags.find(i => i.id === it)).filter(Boolean).map(it => it!!),
                                                    includedGoodsList: extra.goodsList,
                                                    id: Date.now(),
                                                })
                                                props.onChange?.(array)
                                                setEditingValue(undefined)
                                            }} goodsCategories={goodsCategories} goodsBrands={goodsBrands}
                                            goodsBrandTags={goodsBrandTags}/>
    </Space>
}

interface MarketShoppingGuideSalaryPlanListProps {
    goodsCategories: Array<NumberIdAndName>
    goodsBrands: Array<NumberIdAndName>
    goodsBrandTags: Array<NumberIdAndName>
    value?: Array<ConfigureMarketSettlementPlanRuleResponse>
    onChange?: (value: Array<ConfigureMarketSettlementPlanRuleResponse>) => void
}

const MarketSettlementPlanList: React.FC<MarketShoppingGuideSalaryPlanListProps> = (props) => {

    const [editingItemIndex, setEditingItemIndex] = useState<number>()
    const editingValue: ConfigureMarketSettlementPlanRuleRequest | undefined = useMemo(() => {
        if (editingItemIndex !== undefined) {
            let valueElement = props.value?.[editingItemIndex];
            if (valueElement) {

                return {
                    ...valueElement,
                    includedBrandIds: valueElement?.includedBrands?.map(it => it.id) ?? [],
                    includedCategoryIds: valueElement?.includedCategories.map(it => it.id) ?? [],
                    includedBrandTagIds: valueElement?.includedBrandTags.map(it => it.id) ?? [],
                    includedGoodsIds: valueElement?.includedGoodsList.map(it => it.id) ?? [],
                }
            } else {
                return undefined
            }
        } else
            return undefined
    }, [editingItemIndex, props.value]);

    const editingValueGoodsList = useMemo(() => {
        if (editingItemIndex !== undefined) {
            let valueElement = props.value?.[editingItemIndex];
            if (valueElement) {
                return valueElement.includedGoodsList
            } else {
                return undefined
            }
        } else {
            return undefined
        }
    }, [editingItemIndex, props.value])

    let sensors =
        useSensors(useSensor(MouseSensor), useSensor(PointerSensor, {
            activationConstraint: {
                distance: 5,
            }

        }))
    return <>
        <DndContext onDragEnd={event => {
            const {active, over} = event;
            if (active.id !== over?.id) {
                const items: Array<ConfigureMarketSettlementPlanRuleResponse> = props.value ?? []
                const oldIndex = items.findIndex(it => it.id === active.id);
                const newIndex = items.findIndex(it => it.id === over?.id);
                props.onChange?.(arrayMove(items, oldIndex!!, newIndex))
            }
        }} modifiers={[restrictToVerticalAxis]}
                    sensors={sensors}>
            <SortableContext items={props.value?.map(it => it.id) ?? []} strategy={verticalListSortingStrategy}>
                {(props.value ?? []).map((item, index) => {
                    return <MarketSettlementPlanRow editable key={item.id} value={item}
                                                    onEditButtonClick={() => {
                                                                 setEditingItemIndex(index);
                                                             }}
                                                    onDeleteButtonClick={() => {
                                                                 let array = Array.from(props.value ?? [])
                                                                 ArrayUtils.remove(array, item)
                                                                 props.onChange?.(array)
                                                             }}
                    />
                })}
            </SortableContext>
        </DndContext>
        <MarketSettlementPlanRuleFormDrawer open={!!editingValue}
                                            goodsBrandTags={props.goodsBrandTags}
                                            onClose={() => setEditingItemIndex(undefined)}
                                            initialValue={editingValue}
                                            initialGoodsList={editingValueGoodsList}
                                            goodsBrands={props.goodsBrands}
                                            goodsCategories={props.goodsCategories}
                                            onCompleted={(value, extra) => {
                                                let array = Array.from(props.value ?? [])
                                                if (editingItemIndex !== undefined) {
                                                    array[editingItemIndex] = ({
                                                        ...value,
                                                        includedBrands: value.includedBrandIds.map(it => props.goodsBrands.find(i => i.id === it)).filter(Boolean).map(it => it!!),
                                                        includedCategories: value.includedCategoryIds.map(it => props.goodsCategories.find(i => i.id === it)).filter(Boolean).map(it => it!!),
                                                        includedBrandTags: value.includedBrandTagIds.map(it => props.goodsBrandTags.find(i => i.id === it)).filter(Boolean).map(it => it!!),
                                                        includedGoodsList: extra.goodsList,
                                                        id: Date.now()
                                                    })
                                                }
                                                props.onChange?.(array)
                                                setEditingItemIndex(undefined)
                                            }}
        />
    </>
}


export interface MarketSettlementPlanRowProps {
    value: ConfigureMarketSettlementPlanRuleResponse
    onEditButtonClick?: () => void
    onDeleteButtonClick?: () => void
    editable?: boolean
}

export const MarketSettlementPlanRow: React.FC<MarketSettlementPlanRowProps> = (props) => {
    const {
        attributes,
        listeners,
        setNodeRef,
        transform,
        transition,
    } = useSortable({id: props.value.id});
    const draggableStyle = {
        transform: CSS.Transform.toString(transform && {...transform, scaleY: 1}),
        transition,
    };

    const conditionDescriptions = useGoodsMatcherConditions(props.value)

    return <div style={{
        display: "flex",
        justifyContent: "space-between",
        cursor: props.editable ? "move" : "default",
        alignItems: "center", ...draggableStyle
    }} {...listeners} {...attributes} ref={setNodeRef}>
        {props.value && <Space direction={"vertical"}>
            <Typography.Title level={5}>{props.value.name}</Typography.Title>
            {props.value.fixed && <Space>
                <Typography.Text type={"secondary"}>固定费用：{props.value.fixed}</Typography.Text>
            </Space>}
            {props.value.commissionPercentage && <Typography.Text
                type={"secondary"}>扣点比例：{props.value.commissionPercentage.toFixed(2)}%</Typography.Text>}
            {!!conditionDescriptions.length && <Typography.Paragraph>
                <Typography.Text>包含满足以下条件的货品</Typography.Text>
                <ol>
                    {conditionDescriptions.map((it, index) => <li key={index}>{it}</li>)}
                </ol>
            </Typography.Paragraph>}
        </Space>}
        {props.editable && <Space direction={"vertical"}>
            <Button icon={<DeleteOutlined/>} shape={"circle"} danger onClick={() => {
                props.onDeleteButtonClick?.()
            }}/>
            <Button icon={<EditOutlined/>} shape={"circle"} type={"primary"} onClick={props.onEditButtonClick}
            />
        </Space>}
    </div>
}

interface MarketSettlementPlanRuleFormDrawerProps {
    open: boolean
    onClose: () => void
    initialValue?: ConfigureMarketSettlementPlanRuleRequest
    onCompleted: (value: ConfigureMarketSettlementPlanRuleRequest, extra: { goodsList: GoodsItem[] }) => void
    goodsCategories: NumberIdAndName[]
    goodsBrands: NumberIdAndName[]
    goodsBrandTags: NumberIdAndName[]
    initialGoodsList?: GoodsSelectorItem[]
}

function MarketSettlementPlanRuleFormDrawer(props: MarketSettlementPlanRuleFormDrawerProps) {
    const [goodsList, setGoodsList] = useState<GoodsSelectorItem[]>([])
    useEffect(() => {
        if (props.initialGoodsList && props.initialGoodsList.length) {
            setGoodsList(props.initialGoodsList)
        } else {
            setGoodsList([])
        }
    }, [props.initialValue]);
    let [form] = Form.useForm();
    return <FormDrawer<ConfigureMarketSettlementPlanRuleRequest> initialValues={props.initialValue}
                                                                 open={props.open} onClose={props.onClose}
                                                                 title={"编辑结算规则"}
                                                                 form={form}
                                                                 onConfirm={async (values) => {
                                                                     props.onCompleted(values, {goodsList})
                                                                 }}>

        <Row justify={"space-between"} wrap={false} align={"middle"}>
            <Space direction={"vertical"}>
                <Space direction={"horizontal"}>
                    <Form.Item name={"name"} label={"名称"} required={true}
                               rules={[{required: true, message: "请输入名称"}]}>
                        <Input placeholder={"请输入规则名称"}/>
                    </Form.Item>
                    {
                        props.initialValue?.fixed !== undefined ?
                            <>
                                <Form.Item name={"fixedSalary"} required
                                           label={"固定费用"}
                                           rules={[{
                                               required: true,
                                               message: "请输入固定费用"
                                           }]}>
                                    <Input/>
                                </Form.Item>
                            </> : null
                    }
                </Space>
                {
                    props.initialValue?.commissionPercentage !== undefined ? <>
                        <Form.Item name={"commissionPercentage"} required
                                   label={"扣点比例"}>
                            <InputNumber suffix={"%"} max={100} min={0}></InputNumber>
                        </Form.Item>
                        <GoodsMatcherRuleFormItems goodsBrandTags={props.goodsBrandTags} goodsBrands={props.goodsBrands}
                                                   goodsCategories={props.goodsCategories}
                                                   goodsList={goodsList}
                                                   onGoodsListChange={(v, data) => {
                                                       form.setFieldValue("includedGoodsIds", v);
                                                       setGoodsList(data)
                                                   }}/>
                    </> : null
                }

                <Form.Item name={"note"} label={"备注"} required={false}
                           layout={"vertical"}>
                    <TextArea/>
                </Form.Item>
            </Space>
        </Row>
    </FormDrawer>;
}

